home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS08.ADF / Scrimper / scrimper.c < prev    next >
C/C++ Source or Header  |  1986-04-02  |  13KB  |  541 lines

  1. #include <exec/types.h>
  2. #include <exec/memory.h>
  3. #include <intuition/intuition.h>
  4.  
  5. /*
  6. **       S C R E E N   I M A G E   P R I N T E R (SCRIMPER)
  7. **
  8. **             Copyright 1986 By Perry S. Kivolowitz
  9. **
  10. **    The author grants permission to duplicate and reproduce
  11. **    this software  provided  that no commercial gain can be
  12. **    had as a consequence of  use  or  reproduction  of this
  13. **    software and that  this and other identifying informat-
  14. **    be left intact.
  15. **
  16. **    This software is provided as  a  service to the readers
  17. **    of Amazing Computing and does not imply  any commitment
  18. **    on behalf of the author to  provide support nor can the
  19. **    author be held liable  for  the  consequences of use or
  20. **    misuse of this software.
  21. **
  22. */
  23.  
  24. /*
  25. **    Overview
  26. **
  27. **    This program dynamically builds a  list of screens each time its
  28. **    title bar is selected (note that the window this program creates
  29. **    is only as large as its title bar).  The list of screens is dis-
  30. **    played when the right mouse button  is  depressed (and sometimes
  31. **    when it's just feeling lonely too). Select a screen as you would
  32. **    select an item from a menu.
  33. **
  34. **    Something to note is the way the  screen  selection menu centers
  35. **    each item. This is done by  the  routine ``massage_left_edges.''
  36. **
  37. **    After a screen has been  selected,  the screen selection menu is
  38. **    replaced with a function  selection  menu. There  are  currently
  39. **    three things which scrimper allows you to do:
  40. **
  41. **    (1)    Bring the selected screen to front.
  42. **
  43. **        This is  kind of  neat  especially  when  you  have  many
  44. **        screens open  at once. This  gives  you a sort of  direct
  45. **        access capability instead of many repititions of ``screen
  46. **        to front.''
  47. **
  48. **        When the selected screen  comes  to the front if you push 
  49. **        the left mouse button, the  current front most screen be-
  50. **        comes the actual front screen.
  51. **
  52. **        If you click the right mouse  button, the screen SCRIMPER
  53. **        was run from will  come  back  to the front. This is very
  54. **        useful for quickly checking the status of program running
  55. **        on another  screen  and   whipping   back to the original
  56. **        screen.
  57. **
  58. **    (2)    The selected screen can be printed.
  59. **
  60. **        The selected screen will be brought to the front for half
  61. **        a second (literally) just  for  you to make sure you sel-
  62. **        ected the right screen. Then the screen  SCRIMPER was run
  63. **        from comes back to the front and a requester asks if  you
  64. **        really want to print the screen.
  65. **
  66. **        If yes, SCRIMPER will try to  create a copy of the screen
  67. **        in its own dynamically  allocated  memory. If it can, you
  68. **        are free to modify or even delete  the screen without af-
  69. **        fecting the printout.  If  SCRIMPER can't allocate enough
  70. **        CHIP memory, it  will ask  you  (with a requester) if you
  71. **        still want to print the  screen even though SCRIMPER will
  72. **        have to use the *LIVE* copy.  If that's ok, unpredictable
  73. **        results will occur if  you  modify or  delete  the screen
  74. **        while SCRIMPER is printing.
  75. **
  76. **        What's neat here is  that  you can print any screen. Even
  77. **        if your program has no screen dump capability. If it does
  78. **        (for example, DPaint)  SCRIMPER  is  *still  very useful*
  79. **        since it will baby sit  the  printer  rather than forcing
  80. **        (for example) DPaint to do so.
  81. **
  82. **    (3)    Go Back To Screen Select
  83. **
  84. **        This  is the way to  tell  SCRIMPER  to  forget  that you
  85. **        selected a screen.
  86. **
  87. **    Known Bugs:
  88. **
  89. **    (1)    Assumes 640 wide screen.
  90. **
  91. **    (2)    If printer trouble arises and the user aborts by cancelling
  92. **        the print out from the System Requester,  AmigaDos loses 2K
  93. **        of memory and sometimes tosses its cookies.
  94. **
  95. **    
  96. **    Suggested Improvements
  97. **
  98. **    (1)    Allow variable density printing.  The printer driver sup-
  99. **        ports this directly. Very neat C-A!
  100. **
  101. **    (2)    Allow sections of a screen to  be printed. IE: allow user
  102. **        to sweep out a box  over a  screen  and print only what's
  103. **        inside.
  104. **
  105. **    (3)    Adjust for 320 wide screen dynamically.
  106. **
  107. **    Compilation Information
  108. **
  109. **    This code was developed using Manx C Beta 1.99E, 1.99F, and Manx
  110. **    C 3.20A (a final release).
  111. **
  112. **    Defining PRINTF causes printf's to be loaded  which increases the
  113. **    size of the executable to  9160  from 6520 bytes (approximately). 
  114. **    By not defining PRINTF  you  can be confident of SCRIMPER working
  115. **    from the WORKBENCH.
  116. **
  117. **    Link with printer.o
  118. **
  119. **
  120. **    STRONG SUGGESTION: Avoid burning out your print head and ribbon
  121. **               by making the background color of the screen
  122. **               white - I did and got used to it.
  123. */
  124.  
  125. #define    WWIDTH        640
  126. #define    MAX_SCREENS    20
  127. #define    SIZE_MI        (sizeof(struct MenuItem))
  128. #define    SIZE_IT        (sizeof(struct IntuiText))
  129.  
  130. extern void *OpenLibrary();
  131. extern void *GetMsg();
  132. extern void *OpenWindow();
  133. extern void *ItemAddress();
  134.  
  135. int is_cli = 0;
  136. int which_screen = 0;
  137.  
  138. char *window_title = "SCReen IMage PrintER V0.6 (PSKivolowitz)";
  139.  
  140. extern  char *calloc();
  141. struct     IntuitionBase *IntuitionBase;
  142. struct  GfxBase       *GfxBase;
  143. struct     Window *w;
  144. struct     Screen *s[MAX_SCREENS];
  145. char    *stitles[MAX_SCREENS];
  146. struct  IntuiMessage *message;
  147. int     screen_count = 0;
  148.  
  149. extern generic_cleanup();
  150. extern screen_init() , screen_pick();
  151. extern func_init() , func_pick();
  152.  
  153. struct IntuiText print_scrn_it = {
  154.     0 , 1 , JAM2 , 0 , 0 , NULL , (UBYTE *) "print selected screen" , NULL
  155. };
  156.  
  157. struct IntuiText back_2_scrn_it = {
  158.     0 , 1 , JAM2 , 0 , 0 , NULL , (UBYTE *) "return to screen selection" , NULL
  159. };
  160.  
  161. struct IntuiText scrn_2_frnt_it = {
  162.     0 , 1 , JAM2 , 0 , 0 , NULL , (UBYTE *) "selected screen to front" , NULL
  163. };
  164.  
  165. struct MenuItem back_to_screen_select = {
  166.     NULL , -5 , 22 , 0 , 11 , 
  167.     ITEMTEXT | ITEMENABLED | HIGHCOMP ,
  168.     0 , (APTR) &back_2_scrn_it , NULL , NULL , NULL
  169. };
  170.  
  171. struct MenuItem print_screen = {
  172.     &back_to_screen_select , -5 , 11 , 0 , 11 ,
  173.     ITEMENABLED | ITEMTEXT | HIGHCOMP ,
  174.     0 , (APTR) &print_scrn_it , NULL , NULL , NULL
  175. };
  176.  
  177. struct MenuItem screen_to_front = {
  178.     &print_screen , -5 , 0 , 0  , 11 ,
  179.     ITEMTEXT | ITEMENABLED | HIGHCOMP ,
  180.     0 , (APTR) &scrn_2_frnt_it , NULL , NULL , NULL
  181. };
  182.  
  183. struct Menu function_menu = {
  184.     NULL , 
  185.     10 , 0 , 130 , 10 , 
  186.     MENUENABLED ,
  187.     "Select Function" ,
  188.     &screen_to_front
  189. };
  190.  
  191. struct Menu screen_menu = {
  192.     NULL ,
  193.     10 , 0 , 120 , 10 ,
  194.     MENUENABLED ,
  195.     "Select  Screen" , 
  196.     NULL
  197. };
  198.  
  199. struct jmptbl {
  200.     struct Menu *menu;
  201.     int (*init)();
  202.     int (*cleanup)();
  203.     int (*pick)();
  204. };
  205.  
  206. struct jmptbl scrn_jmptbl = {
  207.     &screen_menu ,
  208.     screen_init ,
  209.     generic_cleanup , 
  210.     screen_pick
  211. };
  212.  
  213. struct jmptbl func_jmptbl = {
  214.     &function_menu , 
  215.     func_init ,
  216.     generic_cleanup , 
  217.     func_pick
  218. };
  219.  
  220. struct NewWindow nw = {
  221.     0,10,
  222.     WWIDTH,10,
  223.     -1,-1,
  224.     ACTIVEWINDOW | INACTIVEWINDOW | CLOSEWINDOW | MENUPICK ,
  225.     WINDOWDEPTH | WINDOWDRAG | NOCAREREFRESH | WINDOWCLOSE ,
  226.     NULL,NULL,
  227.     NULL , 
  228.     NULL,NULL,0,0,0,0,WBENCHSCREEN
  229. };
  230.  
  231. #define    IBPtr    struct IntuitionBase * 
  232.  
  233.  
  234. alloc_menu_item(p , i , s)
  235. register struct MenuItem **p;
  236. register char *s;
  237. {
  238.     *p = (struct MenuItem *) calloc(1 , SIZE_MI);
  239.     if (*p) {
  240.         (*p)->NextItem = NULL;
  241.         (*p)->Height   = w->WScreen->Font->ta_YSize;
  242.         (*p)->TopEdge  = i * (*p)->Height;
  243.         (*p)->LeftEdge = -5;
  244.         (*p)->Flags    = ITEMTEXT | ITEMENABLED | HIGHCOMP;
  245.         (*p)->Command  = NULL;
  246.         (*p)->SubItem  = NULL;
  247.         (*p)->NextSelect = NULL;
  248.         (*p)->MutualExclude = (long) ~(1 << i);
  249.         alloc_intuitext(&((*p)->ItemFill) , s);
  250.         if (!(*p)->ItemFill) *p = NULL;
  251.         else (*p)->Width = IntuiTextLength((*p)->ItemFill);
  252.     }
  253. }
  254.  
  255. alloc_intuitext(p , s)
  256. register struct IntuiText **p;
  257. register char  *s;
  258. {
  259.     register char *d = NULL;
  260.     register int length = strlen(s) + 1;
  261.  
  262.     if (length & 1) length++;
  263.     *p = (struct IntuiText *) calloc(1 , SIZE_IT);
  264.     if (*p) {
  265.         d = calloc(1 , length);
  266.         if (d) {
  267.             (*p)->FrontPen  = 0;
  268.             (*p)->BackPen   = 1;
  269.             (*p)->LeftEdge  = 0;
  270.             (*p)->TopEdge   = 0;
  271.             (*p)->DrawMode  = JAM2;
  272.             (*p)->ITextFont = NULL;
  273.             (*p)->NextText  = NULL;
  274.             (*p)->IText     = (UBYTE *) d;
  275.             strcpy(d , s);
  276.         } else *p = NULL;
  277.     }
  278. }
  279.  
  280. #define    EVEN(S)        ((S) & 1 ? (S) + 1 : (S))
  281.  
  282. get_screens()
  283. {
  284.     register int i = 0;
  285.  
  286.     Forbid();
  287.     s[0]       = w->WScreen;
  288.     stitles[0] = calloc(1 , EVEN(strlen(s[0]->Title)+1));
  289.     screen_count = 1;
  290.     if (stitles[0]) {
  291.         strcpy(stitles[0] , s[0]->Title);
  292.         while (s[i++]->NextScreen) {
  293.             s[i] = s[i-1]->NextScreen;
  294.             stitles[i] = calloc(1 , EVEN(strlen(s[i]->Title)+1));
  295.             if (stitles[i]) strcpy(stitles[i] , s[i]->Title);
  296.             else {
  297.                 Permit();
  298.                 return((int) FALSE);
  299.             }
  300.             screen_count++;
  301.         }
  302.     }
  303.     Permit();
  304.     return((int) TRUE);
  305. }
  306.  
  307. build_menu(menu , scrn)
  308. register struct Menu *menu;
  309. register struct Screen *scrn;
  310. {
  311.     register int i;
  312.     register struct MenuItem *p;
  313.  
  314.     if (get_screens()) {
  315.         alloc_menu_item(&menu->FirstItem , 0 , stitles[0]);
  316.         if (!menu->FirstItem) return((int) FALSE);
  317.         p = menu->FirstItem;
  318.         for (i = 1; i < screen_count; i++) {
  319.             alloc_menu_item(&(p->NextItem) , i , stitles[i]);
  320.             if (!p->NextItem) return((int) FALSE);
  321.             p = p->NextItem;
  322.         }
  323.         return((int) TRUE);
  324.     } 
  325.     return((int) FALSE);
  326. }
  327.         
  328. main()
  329. {
  330.     extern void massage_left_edges();
  331.  
  332.     is_cli = 1;
  333.     IntuitionBase = (IBPtr) OpenLibrary("intuition.library" , 0L);
  334.     if (!IntuitionBase) {
  335. #ifdef        PRINTF
  336.         if (is_cli) printf("could not open intuition library\n");
  337. #endif
  338.         exit(1);
  339.     }
  340.     GfxBase = (struct GfxBase *) OpenLibrary("graphics.library" , 0L);
  341.     if (!GfxBase) {
  342. #ifdef        PRINTF
  343.         if (is_cli) printf("could not open graphics library\n");
  344. #endif
  345.         CloseLibrary(IntuitionBase);
  346.         exit(1);
  347.     }
  348.     if (! (w = (struct Window *) OpenWindow(&nw))) {
  349. #ifdef        PRINTF
  350.         if (is_cli) printf("could not open dummy window\n");
  351. #endif
  352.         CloseLibrary(GfxBase);
  353.         CloseLibrary(IntuitionBase);
  354.         exit(1);
  355.     }
  356.     SetWindowTitles(w , window_title ,  -1L);
  357.     set_widths(&function_menu);
  358.     massage_left_edges(&function_menu);
  359.     while (message = (struct IntuiMessage *) GetMsg(w->UserPort)) ReplyMsg(message);
  360.     while (getmenu(&scrn_jmptbl)) ;
  361. out:    while (message = (struct IntuiMessage *) GetMsg(w->UserPort)) ReplyMsg(message);
  362.     SetWindowTitles(w , NULL , NULL);
  363.     CloseWindow(w);
  364.     CloseLibrary(GfxBase);
  365.     CloseLibrary(IntuitionBase);
  366.     exit(0);
  367. }
  368.  
  369. screen_pick(code)
  370. USHORT code;
  371. {
  372.     which_screen = ITEMNUM(code);
  373.     return(getmenu(&func_jmptbl));
  374. }
  375.  
  376.     
  377. freeall()
  378. {
  379.     register int i;
  380.     register struct MenuItem *p = screen_menu.FirstItem;
  381.     register struct IntuiText *t;
  382.     register struct MenuItem *pnext;
  383.  
  384.     for (i = 0; i < screen_count; i++) if (stitles[i]) free(stitles[i]);
  385.     while (p) {
  386.         if (p->ItemFill) {
  387.             t = (struct IntuiText *) p->ItemFill;
  388.             if (t) {
  389.                 if (t->IText) free(t->IText);
  390.                 free(t);
  391.             }
  392.         }
  393.         pnext = p->NextItem;
  394.         free(p);
  395.         p = pnext;
  396.     }
  397.     screen_menu.FirstItem = NULL;
  398.     screen_count = 0;
  399. }
  400.  
  401. void massage_left_edges(menu)
  402. register struct Menu *menu;
  403. {
  404.     register int max_width = 0;
  405.     register struct MenuItem *p = menu->FirstItem;
  406.  
  407.     if (!p) return;
  408.     while (p) {
  409.         if (p->Width > max_width) max_width = p->Width;
  410.         p = p->NextItem;
  411.     }
  412.     p = menu->FirstItem;
  413.     while (p) {
  414.         ((struct IntuiText *) (p->ItemFill))->LeftEdge = (max_width - p->Width) / 2;
  415.         p->Width = max_width;
  416.         p = p->NextItem;
  417.     }
  418. }
  419.  
  420. set_widths(menu)
  421. register struct Menu *menu;
  422. {
  423.     register struct MenuItem *p = menu->FirstItem;
  424.  
  425.     while (p) {
  426.         p->Width = IntuiTextLength(p->ItemFill);
  427.         p = p->NextItem;
  428.     }
  429. }
  430.  
  431. func_pick(code)
  432. USHORT code;
  433. {
  434.     register struct Screen *scrn;
  435.     extern struct Screen *verify_screen_pointer();
  436.     register ULONG class;
  437.  
  438.     if (scrn = verify_screen_pointer())
  439.         switch (ITEMNUM(code)) {
  440.  
  441.         case 2:    return((int) TRUE);
  442.  
  443.         case 1: ClearMenuStrip(w);
  444.             dump_screen(scrn,0,0,scrn->Width,scrn->Height);
  445.             return((int) TRUE);
  446.  
  447.         case 0:    if (scrn == w->WScreen) break;
  448.             ScreenToFront(scrn);
  449.             Wait(1L << w->UserPort->mp_SigBit);
  450.             message = (struct IntuiMessage *) GetMsg(w->UserPort);
  451.             if (message) {
  452.                 class = message->Class;
  453.                 ReplyMsg(message);
  454.                 if (class != INACTIVEWINDOW) ScreenToFront(w->WScreen);
  455.                 if (class == CLOSEWINDOW) return((int) FALSE);
  456.             }
  457.             return((int) TRUE);
  458.     }
  459.     DisplayBeep(w->WScreen);
  460.     return((int) TRUE);
  461. }
  462.  
  463. struct Screen *verify_screen_pointer()
  464. {
  465.     register struct Screen *hoped_for;
  466.     register struct Screen *p;
  467.  
  468.     if (! (hoped_for = s[which_screen])) return(NULL);
  469.     p = s[0];
  470.     while (p) {
  471.         if (p == hoped_for) return(hoped_for);
  472.         p = p->NextScreen;
  473.     }
  474.     return(NULL);
  475. }
  476.  
  477. func_init()
  478. {
  479.     ClearMenuStrip(w);
  480.     SetMenuStrip(w , &function_menu);
  481.     return((int) TRUE);
  482. }
  483.  
  484. generic_cleanup()
  485. {
  486.     ClearMenuStrip(w);
  487.     freeall();
  488. }
  489.  
  490. screen_init()
  491. {
  492.     if (!build_menu(&screen_menu , NULL)) return((int) FALSE);
  493.     massage_left_edges(&screen_menu);
  494.     SetMenuStrip(w , &screen_menu);
  495.     return((int) TRUE);
  496. }
  497.  
  498. getmenu(jmptbl)
  499. register struct jmptbl *jmptbl;
  500. {
  501.     register struct MenuItem *mi;
  502.     register ULONG class;
  503.     register USHORT code , code_save;
  504.     register int ret_val;
  505.  
  506.     
  507.     if (! (*jmptbl->init)()) return((int) FALSE);
  508.     while (1) {
  509.         message = (struct IntuiMessage *) GetMsg(w->UserPort);
  510.         if (!message) {
  511.             Wait(1L << w->UserPort->mp_SigBit);
  512.             continue;
  513.         }
  514.         class = message->Class;
  515.         code  = message->Code;
  516.         ReplyMsg(message);
  517.         switch (class) {
  518.  
  519.             case CLOSEWINDOW:
  520.                 (*jmptbl->cleanup)();
  521.                 return((int) FALSE);
  522.  
  523.             case INACTIVEWINDOW:
  524.             case ACTIVEWINDOW:
  525.                 (*jmptbl->cleanup)();
  526.                 return((int) TRUE);
  527.  
  528.             case MENUPICK:
  529.                 if (code == MENUNULL) continue;
  530.                 while (code != MENUNULL) {
  531.                     mi = (struct MenuItem *) ItemAddress(jmptbl->menu , (long) code);
  532.                     code_save = code;
  533.                     code = mi->NextSelect;
  534.                 }
  535.                 ret_val = (*jmptbl->pick)(code_save);
  536.                 (*jmptbl->cleanup)();
  537.                 return(ret_val);
  538.         }
  539.     }
  540. }
  541.